package com.ghp.admin.interceptor;


import cn.hutool.core.util.StrUtil;
import com.ghp.common.utils.JwtGeneratorUtils;
import com.ghp.common.utils.ThreadLocalUtils;
import com.ghp.common.utils.WebResponseUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import static com.ghp.common.constants.SystemConstants.OPTIONS_METHOD;
import static com.ghp.common.constants.SystemConstants.TOKEN_HEADER_KEY;
import static com.ghp.common.utils.response.ResponseStatus.CLIENT_USER_LOGIN_TIMEOUT;
import static com.ghp.common.utils.response.ResponseStatus.CLIENT_USER_NOT_LOGIN;

/**
 * @author ghp
 * @title 登录拦截器
 * @description
 */
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    /**
     * 拦截需要登录的请求，用于判断用户是否登录
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (request.getMethod().equals(OPTIONS_METHOD)) {
            // 放行所有的OPTIONS请求
            return true;
        }
        // 判断当前用户是否已登录
        if (ThreadLocalUtils.getCurrentId() == null) {
            // 当前用户未登录，直接拦截
            WebResponseUtils.renderString(response, CLIENT_USER_NOT_LOGIN.getMessage());
            return false;
        }
        // 获取token，并判断token是否存在
        String token = request.getHeader(TOKEN_HEADER_KEY);
        if (StrUtil.isBlank(token)) {
            // token不存在，说明当前用户未登录，不需要刷新直接放行（后面的登录拦截器会拦截）
            log.error("token不存在");
            return false;
        }
        // token存在，判断token是否合法
        try {
            JwtGeneratorUtils.parseJWT(token);
        } catch (Exception e) {
            // token超时或非法
            log.error("token超时或非法 \n {}", e.getStackTrace());
            WebResponseUtils.renderString(response, CLIENT_USER_LOGIN_TIMEOUT.getMessage());
            return false;
        }
        // ThreadLocal中有值，token有值并且解析也么有出现异常，则说明用户已成功登录，放行
        return true;
    }
}
